This is a deadlock.
This is a Java and native code level mixed deadlock bug. Native method java.lang.Class#forName0 in thread "Compiling and instantiation 2" and native method java.lang.Class#getDeclaredFields0
in thread "Compiling and instantiation 3" are acquiring the same lock.
And both threads are acquiring the same lock on HashMap instance.
The following
is an example of deadlocked thread dump:
"Compiling and instantiation 3": waiting to lock monitor 0x000000000cc5b3a8 (object 0x00000007d6ce9040,More details about this bug are at GROOVY-4736 JIRA page.
a groovy.lang.GroovyClassLoader$InnerLoader), which is held by "Compiling and instantiation 2"
"Compiling and instantiation 2": waiting to lock monitor 0x000000000cc5bc98 (object 0x00000007d7da8070,
a java.util.HashMap),which is held by "Compiling and instantiation 3"
Java stack information for the threads listed above:
===================================================
"Compiling and instantiation 3":
at java.lang.Class.getDeclaredFields0(Native Method) at java.lang.Class.privateGetDeclaredFields(Class.java:2387) at java.lang.Class.getDeclaredFields(Class.java:1796) at org.codehaus.groovy.vmplugin.v5.Java5.configureClassNode(Java5.java:313) at org.codehaus.groovy.ast.ClassNode.lazyClassInit(ClassNode.java:263) - locked <0x00000007d6fe9090> (a java.lang.Object) at org.codehaus.groovy.ast.ClassNode.getInterfaces(ClassNode.java:341) at org.codehaus.groovy.ast.ClassNode.declaresInterface(ClassNode.java:929) at org.codehaus.groovy.ast.ClassNode.implementsInterface(ClassNode.java:909) at org.codehaus.groovy.classgen.AsmClassGenerator.doConvertAndCast(AsmClassGenerator.java:3842) at org.codehaus.groovy.classgen.AsmClassGenerator.doConvertAndCast(AsmClassGenerator.java:3837) at org.codehaus.groovy.classgen.AsmClassGenerator.storeThisInstanceField(AsmClassGenerator.java:2840) at org.codehaus.groovy.classgen.AsmClassGenerator.visitFieldExpression(AsmClassGenerator.java:2766) at org.codehaus.groovy.ast.expr.FieldExpression.visit(FieldExpression.java:38) at org.codehaus.groovy.classgen.AsmClassGenerator.evaluateEqual(AsmClassGenerator.java:4050) at org.codehaus.groovy.classgen.AsmClassGenerator.visitBinaryExpression(AsmClassGenerator.java:1485) at org.codehaus.groovy.ast.expr.BinaryExpression.visit(BinaryExpression.java:49) at org.codehaus.groovy.classgen.AsmClassGenerator.visitAndAutoboxBoolean(AsmClassGenerator.java:4122) at org.codehaus.groovy.classgen.AsmClassGenerator.visitExpressionStatement(AsmClassGenerator.java:1466) at org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:40) at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:35) at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:165) at org.codehaus.groovy.classgen.AsmClassGenerator.visitBlockStatement(AsmClassGenerator.java:738) at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:69) at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClassCodeContainer(ClassCodeVisitorSupport.java:101) at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitConstructorOrMethod(ClassCodeVisitorSupport.java:112) at org.codehaus.groovy.classgen.AsmClassGenerator.visitStdMethod(AsmClassGenerator.java:626) at org.codehaus.groovy.classgen.AsmClassGenerator.visitConstructorOrMethod(AsmClassGenerator.java:601) at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitConstructor(ClassCodeVisitorSupport.java:119) at org.codehaus.groovy.classgen.AsmClassGenerator.visitConstructor(AsmClassGenerator.java:688) at org.codehaus.groovy.ast.ClassNode.visitContents(ClassNode.java:1035) at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClass(ClassCodeVisitorSupport.java:50) at org.codehaus.groovy.classgen.AsmClassGenerator.visitClass(AsmClassGenerator.java:276) at org.codehaus.groovy.control.CompilationUnit$12.call(CompilationUnit.java:748) at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:942) at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:519) at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:497) at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:474) at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:306) at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:283) - locked <0x00000007d7da8070> (a java.util.HashMap) at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:267) at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:263) at groovy.lang.GroovyClassLoader.recompile(GroovyClassLoader.java:777) - locked <0x00000007d7da8070> (a java.util.HashMap) at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:737) at groovy.lang.GroovyClassLoader$InnerLoader.loadClass(GroovyClassLoader.java:449) at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:793) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:190) at test.C2.class$(test.C2) at test.C2.$get$$class$test$C4(test.C2) at test.C2.<init>(test.C2:7) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:526) at Groovy4736$3.run(Groovy4736.java:169) "Compiling and instantiation 2": at groovy.lang.GroovyClassLoader.recompile(GroovyClassLoader.java:776) - waiting to lock <0x00000007d7da8070> (a java.util.HashMap) at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:737) at groovy.lang.GroovyClassLoader$InnerLoader.loadClass(GroovyClassLoader.java:449) at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:793) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:190) at test.D1.class$(test.D1) at test.D1.$get$$class$test$E3(test.D1) at test.D1.<init>(test.D1:4)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at Groovy4736$3.run(Groovy4736.java:169)
This bug is reproduced under groovy 1.7.9 and JDK 1.6.0_33.
Execute
the following scripts to run the test to reproduce the bug (assume the
location of the groovy test project is groovy_test_home).
Linux:
${groovy_test_home}/scripts/run4736.sh
[--threadnum arg] [--monitoroff]
Windows:
%groovy_test_home%\scripts\run4736.bat
[--threadnum arg] [--monitoroff]
The default argument values will be taken if not specified.For
example,
${groovy_test_home}/scripts/run4736.sh
is
the same as
${groovy_test_home}/scripts/run4736.sh
--threadnum 3
| Option | Function | Default Value | Valid Values |
| --threadnum, -tn | thread number | 3 | integer |
| --monitoroff, -mo | Turn off to stop reporting bug messages and ending program
when the test runs into the expected concurrency bug which is a
deadlock. User has to terminate the program manually when this option is set |